home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Newswatcher 2.0b22 / NW Source / Source / sfutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-11  |  16.2 KB  |  532 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     sfutil.c
  4.  
  5.     This module contains Standard File utility routines.
  6.     
  7.     Copyright © 1994, Northwestern University.
  8.  
  9. ----------------------------------------------------------------------------*/
  10.  
  11. #include <Packages.h>
  12. #include <stdio.h>
  13. #include <Finder.h>
  14. #include <Folders.h>
  15. #include <Aliases.h>
  16.  
  17. #include "glob.h"
  18. #include "sfutil.h"
  19. #include "dialog.h"
  20. #include "menus.h"
  21. #include "newswatcher.h"
  22. #include "strutil.h"
  23. #include "fileutil.h"
  24.  
  25.  
  26.  
  27. #define kDirSelectDlg            200        /* Directory selection standard file dialog */
  28. #define kSelectDirButtonTop     11
  29. #define kSelectDirButtonBottom    10
  30.  
  31. #define kSaveArtDlg                                201        /* Save article standard file dialog */
  32. #define kSaveEncodedCheckbox                    13
  33. #define kSaveThreadsToSeparateFilesCheckbox        14
  34.  
  35. #define kAppendArtDlg                            202        /* Append article standard file dialog */
  36. #define kAppendEncodedCheckbox                    10
  37.  
  38.  
  39.  
  40. static StandardFileReply *gReply;                /* pointer to standard file reply record */
  41. static Boolean *gSaveEncodedText;                /* pointer to save encoded text option */
  42. static Boolean *gSaveThreadsToSeparateFiles;    /* pointer to save threads to separate
  43.                                                    files option */
  44. static AliasHandle gAlias;                        /* handle to alias to default directory, 
  45.                                                    or nil if none */
  46.  
  47. static FSSpec gDirTop;            /* file selected in top button */
  48. static FSSpec gDirBottom;        /* file selected in bottom button */
  49. static short gSelect;            /* 0 = cancel, 1 = top select button, 2 = bottom select button */
  50. static Str255 gPrevNameTop;        /* previous name in top button */
  51. static Str255 gPrevNameBottom;    /* previous name in bottom button */
  52.  
  53. static DlgHookYDUPP gGetPutHookUPP = nil;
  54. static DlgHookYDUPP gMyStandardAppendArticleHookUPP = nil;
  55. static DlgHookYDUPP gMyStandardPutArticleHookUPP = nil;
  56. static ModalFilterYDUPP gSFDialogFilterUPP = nil;
  57. static FileFilterYDUPP gGetDirectoryFilterUPP = nil;
  58. static DlgHookYDUPP gGetDirectoryHookUPP = nil;
  59.  
  60.  
  61.  
  62. /*----------------------------------------------------------------------------
  63.     SetStandardFileDirectoryFromAlias
  64.     
  65.     Initialize the standard file directory from a saved folder alias.
  66.     
  67.     Entry:    gReply = pointer to standard file reply record, or nil if none.
  68.             gAlias = handle to alias.
  69.             
  70.     Exit:    function result = item number which should be returned to
  71.                 standard file. 
  72. ----------------------------------------------------------------------------*/
  73.  
  74. static short SetStandardFileDirectoryFromAlias (void)
  75. {
  76.     short vRefNum, desktopVRefNum;
  77.     long dirID, desktopDirID;
  78.     Boolean valid;
  79.     OSErr err = noErr;
  80.     
  81.     if (gAlias == nil) return sfHookFirstCall;
  82.     ValidateSavedFolderAlias(gAlias, &vRefNum, &dirID, &valid);
  83.     if (!valid) return sfHookFirstCall;
  84.     err = FindFolder(vRefNum, kDesktopFolderType, false, 
  85.         &desktopVRefNum, &desktopDirID);
  86.     if (err == noErr && vRefNum == desktopVRefNum && dirID == desktopDirID) {
  87.         return sfHookGoToDesktop;
  88.     } else {
  89.         gReply->sfFile.vRefNum = vRefNum;
  90.         gReply->sfFile.parID = dirID;
  91.         *gReply->sfFile.name = 0;
  92.         return sfHookChangeSelection;
  93.     }
  94. }
  95.  
  96.  
  97.  
  98. /*----------------------------------------------------------------------------
  99.     SFDialogFilter 
  100.     
  101.     Event filter for standard file dialogs.
  102. ----------------------------------------------------------------------------*/
  103.  
  104. static pascal Boolean SFDialogFilter (DialogPtr dlg, EventRecord *ev, 
  105.     short *itemHit, void *yourDataPtr)
  106. {
  107.     Boolean result = false;
  108.     OSErr err = noErr;
  109.     ModalFilterUPP standardFilterProcUPP;
  110.  
  111.     if (ev->what == updateEvt && (WindowPtr)ev->message != dlg) {
  112.         HandleEvent(ev);
  113.         return false;
  114.     }
  115.     err = GetStdFilterProc(&standardFilterProcUPP);
  116.     if (err == noErr) {
  117.         result = CallModalFilterProc(standardFilterProcUPP, dlg, ev, itemHit);
  118.     }
  119.     return result;
  120. }
  121.  
  122.  
  123.  
  124. /*----------------------------------------------------------------------------
  125.     GetPutHook
  126.     
  127.     Dialog hook function for MyStandardGetFile and MyStandardPutFile.
  128. ----------------------------------------------------------------------------*/
  129.  
  130. static pascal short GetPutHook (short item, DialogPtr dlg, void *myDataPtr)
  131. {
  132.     if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
  133.     if (item == sfHookFirstCall) {
  134.         return SetStandardFileDirectoryFromAlias();
  135.     } else {
  136.         return item;
  137.     }
  138. }
  139.  
  140.  
  141.  
  142. /*----------------------------------------------------------------------------
  143.     MyStandardGetFile 
  144.     
  145.     Present the StandardGetFile dialog.
  146.     
  147.     The parameters are the same as in StandardGetFile, plus:
  148.     
  149.     Entry:    alias = handle to alias to default directory, or nil if none.
  150. ----------------------------------------------------------------------------*/
  151.  
  152. void MyStandardGetFile (FileFilterYDUPP fileFilter, short numTypes,
  153.     char *typeListString, StandardFileReply *reply, AliasHandle alias)
  154. {
  155.     Point where = {-1, -1};
  156.     SFTypeList typeList;
  157.     
  158.     PrepUserInteraction();
  159.     SetMenusTo(kAppleAllDisabled, 0, 0, 0, 0, 0);
  160.     gReply = reply;
  161.     gAlias = alias;
  162.     BlockMoveData(typeListString, typeList, 4*numTypes);
  163.     CustomGetFile(fileFilter, numTypes, typeList, reply, 0, where, gGetPutHookUPP,
  164.         gSFDialogFilterUPP, nil, nil, nil);
  165. }
  166.  
  167.  
  168.  
  169. /*----------------------------------------------------------------------------
  170.     MyStandardPutFile 
  171.     
  172.     Present the StandardPutFile dialog.
  173.     
  174.     The parameters are the same as in StandardPutFile, plus:
  175.     
  176.     Entry:    alias = handle to alias to default directory, or nil if none.
  177. ----------------------------------------------------------------------------*/
  178.  
  179. void MyStandardPutFile (ConstStr255Param prompt, ConstStr255Param defaultName,
  180.     StandardFileReply *reply, AliasHandle alias)
  181. {
  182.     Point where = {-1, -1};
  183.     
  184.     PrepUserInteraction();
  185.     SetMenusTo(kAppleAllDisabled, 0, 0, 0, 0, 0);
  186.     gReply = reply;
  187.     gAlias = alias;
  188.     CustomPutFile(prompt, defaultName, reply, 0, where, gGetPutHookUPP,
  189.         gSFDialogFilterUPP, nil, nil, nil);
  190. }
  191.  
  192.  
  193.  
  194. /*----------------------------------------------------------------------------
  195.     MyStandardAppendArticleHook
  196.     
  197.     Dialog hook function for MyStandardAppendArticle.
  198. ----------------------------------------------------------------------------*/
  199.  
  200. static pascal short MyStandardAppendArticleHook (short item, DialogPtr dlg, 
  201.     void *myDataPtr)
  202. {
  203.     if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
  204.     if (item == kAppendEncodedCheckbox) {
  205.         *gSaveEncodedText = !(*gSaveEncodedText);
  206.         DlgSetCheck(dlg, item, *gSaveEncodedText);
  207.         return sfHookNullEvent;
  208.     } else if (item == sfHookFirstCall) {
  209.         DlgSetCheck(dlg, kAppendEncodedCheckbox, *gSaveEncodedText);
  210.         return SetStandardFileDirectoryFromAlias();
  211.     } else {
  212.         return item;
  213.     }
  214. }
  215.  
  216.  
  217.  
  218. /*----------------------------------------------------------------------------
  219.     MyStandardAppendArticle 
  220.     
  221.     Present the append article dialog, with an extra checkbox to save
  222.     encoded text.
  223.     
  224.     The parameters are the same as in StandardGetFile, plus:
  225.     
  226.     Entry:    *saveEncodedText = default value for save encoded text option.
  227.             alias = handle to alias to default directory, or nil if none.
  228.     
  229.     Exit:    *saveEncodedText = true to save encoded text.
  230. ----------------------------------------------------------------------------*/
  231.  
  232. void MyStandardAppendArticle (FileFilterYDUPP fileFilter, short numTypes,
  233.     char *typeListString, StandardFileReply *reply, Boolean *saveEncodedText,
  234.     AliasHandle alias)
  235. {
  236.     Point where = {-1, -1};
  237.     SFTypeList typeList;
  238.     
  239.     PrepUserInteraction();
  240.     SetMenusTo(kAppleAllDisabled, 0, 0, 0, 0, 0);
  241.     gReply = reply;
  242.     gSaveEncodedText = saveEncodedText;
  243.     gAlias = alias;
  244.     BlockMoveData(typeListString, typeList, 4*numTypes);
  245.     CustomGetFile(fileFilter, numTypes, typeList, reply, kAppendArtDlg, where, 
  246.         gMyStandardAppendArticleHookUPP,
  247.         gSFDialogFilterUPP, nil, nil, nil);
  248. }
  249.  
  250.  
  251.  
  252. /*----------------------------------------------------------------------------
  253.     MyStandardPutArticleHook
  254.     
  255.     Dialog hook function for MyStandardPutArticle.
  256. ----------------------------------------------------------------------------*/
  257.  
  258. static pascal short MyStandardPutArticleHook (short item, DialogPtr dlg, 
  259.     void *myDataPtr)
  260. {
  261.     if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
  262.     if (item == kSaveEncodedCheckbox) {
  263.         *gSaveEncodedText = !(*gSaveEncodedText);
  264.         DlgSetCheck(dlg, item, *gSaveEncodedText);
  265.         return sfHookNullEvent;
  266.     } else if (item == kSaveThreadsToSeparateFilesCheckbox) {
  267.         *gSaveThreadsToSeparateFiles = !(*gSaveThreadsToSeparateFiles);
  268.         DlgSetCheck(dlg, item, *gSaveThreadsToSeparateFiles);
  269.         return sfHookNullEvent;
  270.     } else if (item == sfHookFirstCall) {
  271.         DlgSetCheck(dlg, kSaveEncodedCheckbox, *gSaveEncodedText);
  272.         DlgSetCheck(dlg, kSaveThreadsToSeparateFilesCheckbox, 
  273.             *gSaveThreadsToSeparateFiles);
  274.         return SetStandardFileDirectoryFromAlias();
  275.     } else {
  276.         return item;
  277.     }
  278. }
  279.  
  280.  
  281.  
  282. /*----------------------------------------------------------------------------
  283.     MyStandardPutArticle 
  284.     
  285.     Present the save article dialog, with an extra check box to save
  286.     encoded text.
  287.     
  288.     The parameters are the same as in StandardPutFile, plus:
  289.     
  290.     Entry:    *saveEncodedText = default value for save encoded text option.
  291.             *saveThreadsToSeparateFiles = default value for save threads to
  292.                 separate files options.
  293.             alias = handle to alias to default directory, or nil if none.
  294.     
  295.     Exit:    *saveEncodedText = true to save encoded text.
  296.             *saveThreadsToSeparateFiles = true to save threads to 
  297.                 separate files.
  298. ----------------------------------------------------------------------------*/
  299.  
  300. void MyStandardPutArticle (ConstStr255Param prompt, ConstStr255Param defaultName,
  301.     StandardFileReply *reply, Boolean *saveEncodedText, 
  302.     Boolean *saveThreadsToSeparateFiles, AliasHandle alias)
  303. {
  304.     Point where = {-1, -1};
  305.     
  306.     PrepUserInteraction();
  307.     SetMenusTo(kAppleAllDisabled, 0, 0, 0, 0, 0);
  308.     gReply = reply;
  309.     gSaveEncodedText = saveEncodedText;
  310.     gSaveThreadsToSeparateFiles = saveThreadsToSeparateFiles;
  311.     gAlias = alias;
  312.     CustomPutFile(prompt, defaultName, reply, kSaveArtDlg, where, 
  313.         gMyStandardPutArticleHookUPP,
  314.         gSFDialogFilterUPP, nil, nil, nil);
  315. }
  316.  
  317.  
  318.  
  319. /*----------------------------------------------------------------------------
  320.     GetDirectoryFilter 
  321.     
  322.     Filter function for MyGetStandardDirectory.
  323. ----------------------------------------------------------------------------*/
  324.  
  325. static pascal Boolean GetDirectoryFilter (ParmBlkPtr pb, void *myDataPtr)
  326. {
  327.     return (pb->fileParam.ioFlAttrib & 0x10) == 0 ||
  328.         (pb->fileParam.ioFlFndrInfo.fdFlags & fInvisible) != 0;
  329. }
  330.  
  331.  
  332.  
  333. /*----------------------------------------------------------------------------
  334.     EnableBottomButton 
  335.     
  336.     Enable or disable the bottom directory selection button.
  337.     
  338.     Entry:    dlg = pointer to dialog.
  339.             enabled = true to enable button, false to disable it.
  340. ----------------------------------------------------------------------------*/
  341.  
  342. static void EnableBottomButton (DialogPtr dlg, Boolean enabled)
  343. {
  344.     Handle itemHandle;
  345.     short itemType;
  346.     Rect box;
  347.     Boolean    oldEnable;
  348.  
  349.     GetDialogItem(dlg, kSelectDirButtonBottom, &itemType, &itemHandle, &box);
  350.     oldEnable = (itemType & itemDisable) == 0;
  351.     itemType = enabled ? itemType & (~itemDisable) : itemType | itemDisable;
  352.     SetDialogItem(dlg, kSelectDirButtonBottom, itemType, itemHandle, &box);
  353.     
  354.     if ((itemType & ctrlItem) != 0 && oldEnable != enabled) {
  355.         HiliteControl((ControlHandle)itemHandle, enabled ? 0 : 255);
  356.     }
  357. }
  358.  
  359.  
  360.  
  361. /*----------------------------------------------------------------------------
  362.     GetDirectoryHook
  363.     
  364.     Dialog hook function for MyGetStandardDirectory.
  365. ----------------------------------------------------------------------------*/
  366.  
  367. static pascal short GetDirectoryHook (short item, DialogPtr dlg, void *myDataPtr)
  368. {
  369.     Handle itemHandleTop, itemHandleBottom;
  370.     short itemType;
  371.     Rect boxTop, boxBottom;
  372.     CInfoPBRec pb;
  373.     short width;
  374.     CStr255 buttonTitle;
  375.     Str255 name;
  376.     short foundVRefNum;
  377.     long foundDirID;
  378.     Str255 select;
  379.     CStr255 fmt;
  380.     
  381.     if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
  382.  
  383.     GetPString(kStrFolderSelectNothing, select);
  384.     GetCString(kStrFolderSelectFmt, fmt);
  385.  
  386.     if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
  387.     GetDialogItem(dlg, kSelectDirButtonTop, &itemType, &itemHandleTop, &boxTop);
  388.     GetDialogItem(dlg, kSelectDirButtonBottom, &itemType, &itemHandleBottom, &boxBottom);
  389.     
  390.     if (item == sfHookFirstCall) {
  391.         pb.dirInfo.ioNamePtr = gDirBottom.name;
  392.         pb.dirInfo.ioVRefNum = -LMGetSFSaveDisk();
  393.         pb.dirInfo.ioFDirIndex = -1;
  394.         pb.dirInfo.ioDrDirID = LMGetCurDirStore();
  395.         PBGetCatInfo(&pb, false);
  396.         gDirBottom.vRefNum = pb.dirInfo.ioVRefNum;
  397.         gDirBottom.parID = pb.dirInfo.ioDrParID;
  398.         gDirTop = gDirBottom;
  399.     } else {
  400.         if (gReply->sfIsFolder || gReply->sfIsVolume || gReply->sfType == 'fdrp') {
  401.             gDirBottom = gReply->sfFile;
  402.             EnableBottomButton(dlg, true);
  403.         } else {
  404.             EnableBottomButton(dlg, false);
  405.             *gDirBottom.name = 0;
  406.         }
  407.         if (gReply->sfFile.parID == fsRtParID) {
  408.             FindFolder(kOnSystemDisk, kDesktopFolderType, kCreateFolder,
  409.                 &foundVRefNum, &foundDirID);
  410.             pb.dirInfo.ioNamePtr = gDirTop.name;
  411.             pb.dirInfo.ioVRefNum = foundVRefNum;
  412.             pb.dirInfo.ioFDirIndex = -1;
  413.             pb.dirInfo.ioDrDirID = foundDirID;
  414.             PBGetCatInfo(&pb, false);
  415.             gDirTop.vRefNum = pb.dirInfo.ioVRefNum;
  416.             gDirTop.parID = pb.dirInfo.ioDrParID;
  417.         } else {
  418.             pb.dirInfo.ioNamePtr = gDirTop.name;
  419.             pb.dirInfo.ioVRefNum = gReply->sfFile.vRefNum;
  420.             pb.dirInfo.ioFDirIndex = -1;
  421.             pb.dirInfo.ioDrDirID = gReply->sfFile.parID;
  422.             PBGetCatInfo(&pb, false);
  423.             gDirTop.vRefNum = pb.dirInfo.ioVRefNum;
  424.             gDirTop.parID = pb.dirInfo.ioDrParID;
  425.         }
  426.     }
  427.     
  428.     if (!EqualString(gPrevNameBottom, gDirBottom.name, false, true)) {
  429.         CopyPascalString(gPrevNameBottom, gDirBottom.name);
  430.         width = boxBottom.right - boxBottom.left - StringWidth(select) - 2*CharWidth(' ');
  431.         CopyPascalString(name, gDirBottom.name);
  432.         TruncString(width, name, smTruncMiddle);
  433.         p2cstr(name);
  434.         sprintf(buttonTitle, fmt, name);
  435.         c2pstr(buttonTitle);
  436.         SetControlTitle((ControlHandle)itemHandleBottom, (StringPtr)buttonTitle);
  437.         ValidRect(&boxBottom);
  438.     }
  439.     
  440.     if (!EqualString(gPrevNameTop, gDirTop.name, false, true)) {
  441.         CopyPascalString(gPrevNameTop, gDirTop.name);
  442.         width = boxTop.right - boxTop.left - StringWidth(select) - 2*CharWidth(' ');
  443.         CopyPascalString(name, gDirTop.name);
  444.         TruncString(width, name, smTruncMiddle);
  445.         p2cstr(name);
  446.         sprintf(buttonTitle, fmt, name);
  447.         c2pstr(buttonTitle);
  448.         SetControlTitle((ControlHandle)itemHandleTop, (StringPtr)buttonTitle);
  449.         ValidRect(&boxTop);
  450.     }
  451.     
  452.     /* Handle clicks on Select and Cancel buttons. */
  453.     
  454.     if (item == kSelectDirButtonTop) {
  455.         gSelect = 1;
  456.         return sfItemCancelButton;
  457.     } else if (item == kSelectDirButtonBottom) {
  458.         gSelect = 2;
  459.         return sfItemCancelButton;
  460.     } else if (item == sfItemCancelButton) {
  461.         gSelect = 0;
  462.         return sfItemCancelButton;
  463.     }
  464.     
  465.     return item;
  466. }
  467.  
  468.  
  469.  
  470. /*----------------------------------------------------------------------------
  471.     MyStandardGetDirectory 
  472.     
  473.     Present a custom standard get file dialog to select a directory.
  474.         
  475.     Exit:    reply->sfGood = true if directory selected, false if dialog canceled.    
  476.             reply->sfFile.vRefNum = vol ref num of selected directory.
  477.             reply->sfFile.parID = directory id of *parent* of selected directory.
  478.             reply->sfFile.name = name of selected directory.
  479.             *dirID = directory id of selected directory.
  480. ----------------------------------------------------------------------------*/
  481.  
  482. void MyStandardGetDirectory (StandardFileReply *reply, long *dirID)
  483. {
  484.     Point point = {-1,-1};
  485.     CInfoPBRec pb;
  486.     Boolean targetIsFolder, wasAliased;
  487.     
  488.     PrepUserInteraction();
  489.     SetMenusTo(kAppleAllDisabled, 0, 0, 0, 0, 0);
  490.  
  491.     *gPrevNameTop = *gPrevNameBottom = 0;
  492.     gReply = reply;
  493.     
  494.     CustomGetFile(gGetDirectoryFilterUPP, -1, nil, reply, kDirSelectDlg, point,
  495.         gGetDirectoryHookUPP, gSFDialogFilterUPP, nil, nil, nil);
  496.         
  497.     reply->sfGood = gSelect != 0;
  498.     if (!reply->sfGood) return;
  499.     
  500.     if (gSelect == 1) {
  501.         reply->sfFile = gDirTop;
  502.     } else {
  503.         reply->sfFile = gDirBottom;
  504.     }
  505.     ResolveAliasFile(&reply->sfFile, true, &targetIsFolder, &wasAliased);
  506.  
  507.     pb.dirInfo.ioNamePtr = reply->sfFile.name;
  508.     pb.dirInfo.ioVRefNum = reply->sfFile.vRefNum;
  509.     pb.dirInfo.ioFDirIndex = 0;
  510.     pb.dirInfo.ioDrDirID = reply->sfFile.parID;
  511.     PBGetCatInfo(&pb, false);
  512.     *dirID = pb.dirInfo.ioDrDirID;       
  513. }
  514.  
  515.  
  516.  
  517. /*----------------------------------------------------------------------------
  518.     sfutil_InitUPP
  519.     
  520.     Initialize UPPs.
  521. ----------------------------------------------------------------------------*/
  522.  
  523. void sfutil_InitUPP (void)
  524. {
  525.      gGetDirectoryFilterUPP = NewFileFilterYDProc(GetDirectoryFilter);
  526.     gGetDirectoryHookUPP = NewDlgHookYDProc(GetDirectoryHook);
  527.     gSFDialogFilterUPP = NewModalFilterYDProc(SFDialogFilter);
  528.     gGetPutHookUPP = NewDlgHookYDProc(GetPutHook);
  529.     gMyStandardPutArticleHookUPP = NewDlgHookYDProc(MyStandardPutArticleHook);
  530.     gMyStandardAppendArticleHookUPP = NewDlgHookYDProc(MyStandardAppendArticleHook);
  531. }
  532.